package com.duobaoyu.dby.supply.biz.strategy.message.order.confirm;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.duobaoyu.dby.channel.adapter.bean.message.order.OrderMessage;
import com.duobaoyu.dby.channel.adapter.enums.BizMessageTypeEnum;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.order.OrderStatusEnum;
import com.duobaoyu.dby.channel.strategy.supply.impl.real.xingyun.callback.order.XingYunOrderGenerateCallback;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.common.mybatis.config.IdGeneratorSnowflake;
import com.duobaoyu.dby.supply.biz.constant.OperateSourceConstants;
import com.duobaoyu.dby.supply.biz.constant.OrderOperateConstants;
import com.duobaoyu.dby.supply.biz.enums.OrderParentTypeEnum;
import com.duobaoyu.dby.supply.biz.producer.SupplyChainMQProducer;
import com.duobaoyu.dby.supply.biz.service.order.OrderService;
import com.duobaoyu.dby.supply.biz.strategy.message.order.base.BaseOrderAsyncHandler;
import com.duobaoyu.dby.supply.common.biz.bo.message.ChannelMessageBO;
import com.duobaoyu.dby.supply.db.entity.order.Order;
import com.duobaoyu.dby.supply.db.entity.order.OrderConsignee;
import com.duobaoyu.dby.supply.db.entity.order.OrderProduct;
import com.duobaoyu.dby.supply.db.repository.order.OrderConsigneeRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderProductRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderRepository;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;

@Slf4j
@Component
@RequiredArgsConstructor
public class XingYunOrderConfirmChangeAsyncHandler extends BaseOrderAsyncHandler {

	private final OrderService orderService;
	private final OrderRepository orderRepository;
	private final IdGeneratorSnowflake idGeneratorSnowflake;
	private final OrderProductRepository orderProductRepository;
	private final TransactionTemplate transactionTemplate;
	private final SupplyChainMQProducer supplyChainMQProducer;
	private final OrderConsigneeRepository orderConsigneeRepository;


	@Override
	protected Set<String> channelCodes() {
		return Sets.newHashSet(ChannelCodeEnum.XING_YUN.getValue());
	}

	@Override
	protected Set<Integer> bizMessageTypes() {
		return Sets.newHashSet(BizMessageTypeEnum.CONFIRM_ORDER.getValue());
	}


	@Override
	protected Boolean executeHandler(ChannelMessageBO channelMessage, Object beforeResult) {
		String data = JSON.parseObject(channelMessage.getOriginalMessage()).getString("data");
		XingYunOrderGenerateCallback xingYunOrderGenerateCallback = JSON.parseObject(data, XingYunOrderGenerateCallback.class);
		Order order = orderRepository.getOne(Wrappers.<Order>lambdaQuery().eq(Order::getOrderTradeSn, xingYunOrderGenerateCallback.getMerchantOrderId())
				.eq(Order::getChannelCode, channelMessage.getChannelCode()));

		if (ObjectUtils.isEmpty(order)) {
			log.info("message:{},channelCode:{},data:{}","确认回调失败",channelMessage.getChannelCode(),JSON.toJSONString(channelMessage));
			return Boolean.FALSE;
		}
		orderStateCheck(order);

		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(@NotNull TransactionStatus transactionStatus) {
				if (Objects.equals(xingYunOrderGenerateCallback.getSuccess(),CommonConstants.ONE)) {
					List<OrderProduct> orderProductList = orderProductRepository.list(Wrappers.<OrderProduct>lambdaQuery().eq(OrderProduct::getOrderSn, order.getOrderSn()));
					OrderConsignee orderConsignee = orderConsigneeRepository.getOne(Wrappers.<OrderConsignee>lambdaQuery().eq(OrderConsignee::getOrderSn, order.getOrderSn()));

					List<Order> orderList = Lists.newArrayList();
					List<OrderProduct> orderProductCopyList = Lists.newArrayList();
					List<OrderConsignee> orderConsigneeList = Lists.newArrayList();

					xingYunOrderGenerateCallback.getOrderDetails().forEach(item -> {
						List<XingYunOrderGenerateCallback.SkuInfo> skuInfos = item.getSkuInfos();
						List<OrderProduct> orderProductNewList = Lists.newArrayList();
						for (OrderProduct orderProduct : orderProductList) {
							for (XingYunOrderGenerateCallback.SkuInfo skuInfo : skuInfos) {
								if (orderProduct.getChannelSkuCode().contains(String.valueOf(skuInfo.getSkuId()))) {
									OrderProduct clone = orderProduct.clone();
									clone.setId(idGeneratorSnowflake.snowflakeId());
									clone.setSkuNum(skuInfo.getBuyNum());
									orderProductNewList.add(clone);
								}
							}
						}
						reckon(orderProductList);
						Order clone = order.clone();
						clone.setChannelOrderSn(item.getChildOrderId());
						clone.setChannelTradeOrderSn(xingYunOrderGenerateCallback.getOrderId());
						Order orderOne = createOrder(clone, orderProductList);
						orderOne.setChannelActualFreightAmount(StringUtils.isNotBlank(item.getFreightAmount()) ? new BigDecimal(item.getFreightAmount()) : null);
						orderProductNewList.forEach(orderProduct -> orderProduct.setOrderSn(orderOne.getOrderSn()));

						orderConsignee.setId(idGeneratorSnowflake.snowflakeId());
						orderConsignee.setOrderSn(orderOne.getOrderSn());

						orderList.add(orderOne);
						orderProductCopyList.addAll(orderProductNewList);
						orderConsigneeList.add(orderConsignee);
					});
					orderRepository.update(Wrappers.<Order>lambdaUpdate().set(Order::getParentType, OrderParentTypeEnum.BEFORE_SPLIT.getValue())
					.eq(Order::getId,order.getId()));
					orderRepository.saveBatch(orderList);
					orderProductRepository.saveBatch(orderProductCopyList);
					orderConsigneeRepository.saveBatch(orderConsigneeList);
				} else {
					OrderMessage orderMessage = JSON.parseObject(channelMessage.getMessage(), OrderMessage.class);
					OrderStatusEnum orderSubStatusOld = OrderStatusEnum.getOrderSubStatusEnum(order.getOrderStatus());
					OrderStatusEnum orderSubStatusNew = OrderStatusEnum.getOrderSubStatusEnum(OrderStatusEnum.FAILURE.getValue());
					orderService.updateStatusByOrderSnList(Collections.singletonList(order.getOrderSn()), orderSubStatusNew, orderSubStatusOld, OperateSourceConstants.OPERATION_CHANNEL, OrderOperateConstants.CHANNEL_PART_SEND,orderMessage.getFailReason());
				}
			}
		});
		supplyChainMQProducer.orderAlterSend(order.getSupplyTradeSn(), order.getServerName());
		return Boolean.TRUE;
	}
}
